#include "Animation.hpp"

namespace sl
{
	Animation::Animation() : SpriteObject(), mySize(sf::Vector2i(1, 1)), myOffset(sf::Vector2i(0, 0)), myTicks(RenderScreen->GetFramerate()), myTick(0), myCurFrame(0), myIsRunning(false)
	{}

	Animation::Animation(sf::Texture* img, const sf::Vector2i& size) : SpriteObject(img), mySize(size), myOffset(sf::Vector2i(0, 0)), myTicks(RenderScreen->GetFramerate()), myTick(0), myCurFrame(0), myIsRunning(false)
	{}

	Animation::Animation(const Animation& anim) : SpriteObject(const_cast<sf::Texture*>(anim.GetTexture())), mySize(anim.mySize), myOffset(anim.myOffset), myTicks(anim.myTicks), myTick(0), myCurFrame(0), myIsRunning(false)
	{}

	Animation* Animation::AddFrame(const FrameInfo& info)
	{
		myFrameInfos.push_back(info);
		return this;
	}

	Animation* Animation::AddFrame(unsigned int frame, unsigned int delay, const sf::Vector2i& offset)
	{
		return AddFrame(FrameInfo(frame, delay, offset));
	}

	Animation* Animation::SetSize(const sf::Vector2i& size)
	{
		mySize = size;
		return this;
	}

	sf::IntRect Animation::GetFrame()
	{
		return GetFrame(myFrameInfos[myCurFrame]);
	}

	sf::IntRect Animation::GetFrame(unsigned int index)
	{
		if (index < mySize.x * mySize.y)
		{
			sf::Vector2i size(GetTexture()->GetWidth() / mySize.x, GetTexture()->GetHeight() / mySize.y);
			return sf::IntRect(size.x * (mySize.x % index), size.y * (mySize.x / index), size.x, size.y); 
		}

		return sf::IntRect(); 
	}

	sf::IntRect Animation::GetFrame(FrameInfo& info)
	{
		if (info.GetFrame() < mySize.x * mySize.y)
		{
			sf::Vector2i size(GetTexture()->GetWidth() / mySize.x, GetTexture()->GetHeight() / mySize.y);
			return sf::IntRect(size.x * (info.GetFrame() % mySize.x), size.y * (info.GetFrame() / mySize.y), size.x, size.y);
		}

		return sf::IntRect();
	}

	Animation* Animation::SetOffset(FrameInfo& info)
	{
		Move(-myOffset.x, -myOffset.y);
		myOffset = info.GetOffset();
		Move(myOffset.x, myOffset.y);
		return this;
	}

	Animation* Animation::Start()
	{
		myIsRunning = true;
		if (myFrameInfos.size() > 0)
		{
			SetSubRect(GetFrame(myFrameInfos[myCurFrame]));
			SetOffset(myFrameInfos[myCurFrame]);
		}
		return this;
	}

	Animation* Animation::Stop()
	{
		myIsRunning = false;
		if (myFrameInfos.size() > 0)
			SetSubRect(sf::IntRect(0, 0, GetTexture()->GetWidth(), GetTexture()->GetHeight()));
		return this;
	}

	Animation* Animation::Pause()
	{
		myIsRunning = !myIsRunning;
		return this;
	}

	Animation* Animation::Restart()
	{
		Start();
		return Stop();
	}

	Animation* Animation::Update(float time)
	{
		if (myIsRunning)
		{
			unsigned int tick = time * myTicks;
			if (myFrameInfos.size() > 0 && tick >= 1)
			{
				tick += myTick;
				while (tick >= myFrameInfos[myCurFrame].GetDelay())
				{
					tick -= myFrameInfos[myCurFrame].GetDelay();
					myCurFrame++;
					if (myCurFrame >= myFrameInfos.size())
						myCurFrame = 0;
				}

				myTick = tick;

				SetSubRect(GetFrame(myFrameInfos[myCurFrame]));
				SetOffset(myFrameInfos[myCurFrame]);
			}
		}

		return this;
	}

	bool Animation::IsRunning()
	{
		return myIsRunning;
	}
}